//
//  GCDViewController.m
//  Gunterapple
//
//  Created by 热带雨林 on 2021/1/15.
//  Copyright © 2021 热带雨林. All rights reserved.
//

#import "GCDViewController.h"
#import "NSObject+shareTestThread.h"


static NSInteger tick = 5;
@interface GCDViewController ()
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) NSThread *thread1;
@property (nonatomic, strong) NSThread *thread2;

@property (nonatomic, assign) NSInteger tickNum;
@end

@implementation GCDViewController

- (void)viewDidLoad {

    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    self.tickNum = 5;
    /**
     多线程
     1.pthread   几乎不用
     2.NSthread 苹果提供的一种面向对象的轻量级的多线程技术
     3.GCD
     */
    //创建线程
//    [self thread];
    //线程之间通讯
//    [self threadPort];
    //GCD创建线程
//    [self creatGCD];
    //GCD 线程中的通信
//    [self portGCD];
    //栅栏方法
//    [self barrierGCD];
    //延时
//    [self threadAfter];
    //快速迭代
//    [self apply];
    //线程组
//    [self group];
    //进入或者退出
//    [self enterOrLeave];
    //信号量semaphore
//    [self semaphore];
    //后台常驻线程
//    [self testThread];
    //信号量 最大并发数
//    [self threadPool];
//    [self GCDPool];
//    [self threadStatusNoSafe];
//    [self test];
//    [self testII];
    [self testSSS];
}

- (void)testSSS{
 
    
}

- (void)test{
    __block int a  = 0;
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    while (a < 5) {
        //全局并发队列中 如果想修改数据
        dispatch_async(queue, ^{
            a++;
        });
    }
    NSLog(@" ======= %d",a); //---> 结果不确定
}

- (void)testII{
    __block int a  = 0;
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    while (a < 5) {
        dispatch_sync(queue, ^{
            a++;
        });
    }
    NSLog(@"%d",a); // --> 5
}


#pragma mark - NSThread线程安全与线程同步
- (void)threadStatusNoSafe{
    self.thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(seal) object:nil];
    self.thread1.name = @"窗口1";
//    self.thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(seal) object:nil];
//    self.thread2.name = @"窗口2";
    [self.thread1 start];
//    [self.thread2 start];
    
    //创建之后自动开启
    [NSThread detachNewThreadSelector:@selector(seal) toTarget:self withObject:nil];
    
    [self performSelectorInBackground:@selector(seal) withObject:nil];
    
    [NSThread detachNewThreadWithBlock:^{
        [self seal];
    }];
    
}
- (void)seal{
    while (1) {
        //同步锁 互斥锁 相当于semphore
        @synchronized (self) {
            if(self.tickNum > 0){
                self.tickNum --;
                NSLog(@"已买一张，剩余票数：%ld，窗口:%@",(long)self.tickNum,[NSThread currentThread]);
                [NSThread sleepForTimeInterval:0.2];
            }else{
                NSLog(@"所有火车票均已售完");
                break;
            }
        }
    }
}

#pragma mark - GCD最大并发数
- (void)GCDPool{
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i < 9; i ++) {
        dispatch_async(queue, ^{
            NSLog(@"%@ -- %d",[NSThread currentThread],i);
        });
    }
    NSLog(@"end");
}
#pragma mark - 实现指定线程数目的线程池  设置最大并发数  不懂
- (void)threadPool{
    //通过信号量实现线程同步，控制最大并发数
    dispatch_queue_t concurrentQueue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t selQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
    //指定最大并发数
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
    for (int i = 0; i < 5; i ++) {
        dispatch_async(selQueue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_async(concurrentQueue, ^{
                NSLog(@"thread-info:%@开始执行任务%d",[NSThread currentThread],(int)i);
                sleep(1);
                NSLog(@"thread-info:%@结束执行任务%d",[NSThread currentThread],(int)i);
                dispatch_semaphore_signal(semaphore);
            });
        });
    }
}

#pragma mark - 后台常驻线程
- (void)testThread{
    [self performSelector:@selector(click) onThread:[NSObject shareThread] withObject:nil waitUntilDone:NO];
}
#pragma mark - semaphore
- (void)semaphore{
    //同步锁
    /**
     2021-01-20 15:17:39.869914+0800 Gunterapple[8951:576530] begin -- <NSThread: 0x6000022cfd00>{number = 1, name = main}
     2021-01-20 15:17:42.039936+0800 Gunterapple[8951:576579] 1 -- <NSThread: 0x600002290fc0>{number = 6, name = (null)}
     2021-01-20 15:17:53.845593+0800 Gunterapple[8951:576530] end -- <NSThread: 0x6000022cfd00>{number = 1, name = main} 6
     */
    //1.异步变同步 2.保证线程安全
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    //创建信号量，并初始化信号量总量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    /**
    执行完之后 创建信号量并初始化信号量总量
     <OS_dispatch_semaphore: semaphore[0x600000fc6c60] = { xref = 3, ref = 1, port = 0x0, value = 0, orig = 0 }>
     value是0
     */
    NSLog(@"begin -- %@",[NSThread currentThread]);
    __block int num = 3;
    dispatch_async(queue, ^{
        NSLog(@"1 -- %@",[NSThread currentThread]);
        num = 6;
        //解锁  wait 之后的代码就开始执行了
        dispatch_semaphore_signal(semaphore);
        /**
         执行完之后，value为0  解锁 不在阻塞当前线程 开始执行wait之后的代码 <OS_dispatch_semaphore: semaphore[0x600000fc6c60] = { xref = 2, ref = 1, port = 0x2107, value = 0, orig = 0 }>
         */
    });
    //加锁
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    /**
     执行完之后，信号量j减为负数，开始阻塞当前线程 wait之后的代码就不执行了，这时开始执行异步中的任务
     <OS_dispatch_semaphore: semaphore[0x600000fc6c60] = { xref = 3, ref = 1, port = 0x2107, value = -1, orig = 0 }>
     */
    NSLog(@"end -- %@ %d ",[NSThread currentThread],num);
    
}
#pragma mark - enter/leave
- (void)enterOrLeave{
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    NSLog(@"begin -- %@",[NSThread currentThread]);
    //追加一个任务到队列组中
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"1 -- %@",[NSThread currentThread]);
        //任务执行完毕之后 退出任务组
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"2 -- %@",[NSThread currentThread]);
        //任务执行完毕之后 退出任务组
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"3 -- %@",[NSThread currentThread]);
        //任务执行完毕之后 退出任务组
        dispatch_group_leave(group);
    });
    //notify监听到group中未执行完任务数为0之后，追加任务到notify中回到主线程刷新UI
    dispatch_group_notify(group, mainQueue, ^{
        //回到主线程刷新UI
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
}
#pragma mark - group
- (void)group{
    /**
     2021-01-20 14:41:56.181240+0800 Gunterapple[8400:555746] begin -- <NSThread: 0x6000025321c0>{number = 1, name = main}
     2021-01-20 14:41:56.181447+0800 Gunterapple[8400:555746] end -- <NSThread: 0x6000025321c0>{number = 1, name = main}
     2021-01-20 14:41:58.184107+0800 Gunterapple[8400:555918] 2 -- <NSThread: 0x60000256f940>{number = 3, name = (null)}
     2021-01-20 14:41:58.184107+0800 Gunterapple[8400:555919] 1 -- <NSThread: 0x6000025bf680>{number = 8, name = (null)}
     //最后回到主线程刷新UI
     2021-01-20 14:42:00.185547+0800 Gunterapple[8400:555746] 3 -- <NSThread: 0x6000025321c0>{number = 1, name = main}
     */
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    //创建线程组
    dispatch_group_t group = dispatch_group_create();
    //将队列添加到线程组中
    NSLog(@"begin -- %@",[NSThread currentThread]);
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"1 -- %@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"2 -- %@",[NSThread currentThread]);
    });
    //监听group中的任务，线程组中的任务完成之后，追加新的任务到线程组中
    dispatch_group_notify(group, mainQueue, ^{
        //回到主线程刷新UI
        [NSThread sleepForTimeInterval:2.0];
        NSLog(@"3 -- %@",[NSThread currentThread]);
    });
    //阻塞当前线程
    /**
     2021-01-20 14:52:01.618435+0800 Gunterapple[8547:561602] begin -- <NSThread: 0x600002cfadc0>{number = 1, name = main}
     2021-01-20 14:52:03.620017+0800 Gunterapple[8547:561735] 1 -- <NSThread: 0x600002ca70c0>{number = 3, name = (null)}
     2021-01-20 14:52:03.620086+0800 Gunterapple[8547:561741] 2 -- <NSThread: 0x600002cac740>{number = 5, name = (null)}
     2021-01-20 14:52:03.620414+0800 Gunterapple[8547:561602] end -- <NSThread: 0x600002cfadc0>{number = 1, name = main}
     2021-01-20 14:52:05.642545+0800 Gunterapple[8547:561602] 3 -- <NSThread: 0x600002cfadc0>{number = 1, name = main}
     //等子线程中的任务全部执行完毕之后，在回到主线程中
     */
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"end -- %@",[NSThread currentThread]);
}
#pragma mark - apply
- (void)apply{
    /**
     //在子线程中执行
     2021-01-20 11:53:35.821784+0800 Gunterapple[7791:490368] begin -- <NSThread: 0x6000005d5c00>{number = 1, name = main}
     2021-01-20 11:53:35.821975+0800 Gunterapple[7791:490368] end -- <NSThread: 0x6000005d5c00>{number = 1, name = main}
     2021-01-20 11:53:35.822051+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 0
     2021-01-20 11:53:35.822270+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 1
     2021-01-20 11:53:35.822603+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 2
     2021-01-20 11:53:35.824465+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 3
     2021-01-20 11:53:35.824864+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 4
     2021-01-20 11:53:35.825977+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 5
     2021-01-20 11:53:35.828495+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 6
     2021-01-20 11:53:35.828743+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 7
     2021-01-20 11:53:35.828988+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 8
     2021-01-20 11:53:35.829105+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 9
     2021-01-20 11:53:35.829208+0800 Gunterapple[7791:490440] index -- <NSThread: 0x600000541080>{number = 6, name = (null)} 10
     2021-01-20 11:53:35.829362+0800 Gunterapple[7791:490527] index -- <NSThread: 0x600000541a00>{number = 8, name = (null)} 11
     2021-01-20 11:53:35.830611+0800 Gunterapple[7791:490446] index -- <NSThread: 0x60000054f380>{number = 7, name = (null)} 12
     
     //
     2021-01-20 11:56:33.914918+0800 Gunterapple[7826:492414] begin -- <NSThread: 0x6000006e9ec0>{number = 1, name = main}
     
     2021-01-20 11:56:33.915164+0800 Gunterapple[7826:492414] index -- <NSThread: 0x6000006e9ec0>{number = 1, name = main} 0
     2021-01-20 11:56:33.915245+0800 Gunterapple[7826:492506] index -- <NSThread: 0x6000006637c0>{number = 7, name = (null)} 1
     2021-01-20 11:56:33.915326+0800 Gunterapple[7826:492414] index -- <NSThread: 0x6000006e9ec0>{number = 1, name = main} 2
     2021-01-20 11:56:33.915415+0800 Gunterapple[7826:492506] index -- <NSThread: 0x6000006637c0>{number = 7, name = (null)} 3
     2021-01-20 11:56:33.915454+0800 Gunterapple[7826:492414] index -- <NSThread: 0x6000006e9ec0>{number = 1, name = main} 4
     2021-01-20 11:56:33.915531+0800 Gunterapple[7826:492506] index -- <NSThread: 0x6000006637c0>{number = 7, name = (null)} 5
     2021-01-20 11:56:33.915622+0800 Gunterapple[7826:492414] index -- <NSThread: 0x6000006e9ec0>{number = 1, name = main} 6
     2021-01-20 11:56:33.915678+0800 Gunterapple[7826:492506] index -- <NSThread: 0x6000006637c0>{number = 7, name = (null)} 7
     2021-01-20 11:56:33.916246+0800 Gunterapple[7826:492414] index -- <NSThread: 0x6000006e9ec0>{number = 1, name = main} 8
     2021-01-20 11:56:33.916471+0800 Gunterapple[7826:492506] index -- <NSThread: 0x6000006637c0>{number = 7, name = (null)} 9
     2021-01-20 11:56:33.916582+0800 Gunterapple[7826:492501] index -- <NSThread: 0x600000690dc0>{number = 6, name = (null)} 10
     2021-01-20 11:56:33.916881+0800 Gunterapple[7826:492495] index -- <NSThread: 0x600000668700>{number = 8, name = (null)} 11
     2021-01-20 11:56:33.916980+0800 Gunterapple[7826:492414] index -- <NSThread: 0x6000006e9ec0>{number = 1, name = main} 12
     
     2021-01-20 11:56:33.917832+0800 Gunterapple[7826:492414] end -- <NSThread: 0x6000006e9ec0>{number = 1, name = main}
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    NSLog(@"begin -- %@",[NSThread currentThread]);
//    dispatch_async(queue, ^{
//        dispatch_apply(13, queue, ^(size_t index) {
//               NSLog(@"index -- %@ %ld",[NSThread currentThread],index);
//           });
//    });
    
    dispatch_apply(13, queue, ^(size_t index) {
        NSLog(@"index -- %@ %ld",[NSThread currentThread],index);
    });
    NSLog(@"end -- %@",[NSThread currentThread]);
}
#pragma mark - 四种延时方法
- (void)threadAfter{
    //
    /**
     2021-01-20 11:10:15.075333+0800 Gunterapple[7141:462517] currentThread -- <NSThread: 0x600000dfedc0>{number = 1, name = main}
     2021-01-20 11:10:18.075919+0800 Gunterapple[7141:462657] after --- <NSThread: 0x600000d8b340>{number = 6, name = (null)} end
     在子线程上执行
     */
    //1.dispatch_after //非阻塞式
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t currentQueue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
//    NSLog(@"currentThread -- %@",[NSThread currentThread]);
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), queue, ^{
//        //3秒之后，执行
//        NSLog(@"after --- %@ end",[NSThread currentThread]);
//    });
    //2.afterDelay 非阻塞式
//    NSLog(@"begin -- %@",[NSThread currentThread]);
//    dispatch_async(queue, ^{
//        NSLog(@"after -- %@",[NSThread currentThread]);
//        //在子线程中 需要获取当前子线程中的runloop
//        [self performSelector:@selector(click) withObject:nil afterDelay:2.0f];
//        [[NSRunLoop currentRunLoop] run];
//    });
//    NSLog(@"end -- %@",[NSThread currentThread]);
    //3.TimeInterval  非阻塞式
    /**
     2021-01-20 11:39:17.109227+0800 Gunterapple[7489:479684] begin -- <NSThread: 0x6000030ace00>{number = 1, name = main}
     2021-01-20 11:39:17.109423+0800 Gunterapple[7489:479684] end -- <NSThread: 0x6000030ace00>{number = 1, name = main}
     2021-01-20 11:39:17.109423+0800 Gunterapple[7489:479814] after -- <NSThread: 0x6000030c87c0>{number = 6, name = (null)}
     2021-01-20 11:39:19.113082+0800 Gunterapple[7489:479814] currentThread1 -- <NSThread: 0x6000030c87c0>{number = 6, name = (null)}
     */
//    NSLog(@"begin -- %@",[NSThread currentThread]);
//    //取消当前线程的所有操作
////    [NSObject cancelPreviousPerformRequestsWithTarget:self];
//    dispatch_async(queue, ^{
//        //在子线程中需要开启当前线程的runloop
//        NSLog(@"after -- %@",[NSThread currentThread]);
//        self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0f target:self selector:@selector(click) userInfo:nil repeats:NO];
//        [[NSRunLoop currentRunLoop] run];
//    });
//    NSLog(@"end -- %@",[NSThread currentThread]);
    
    //4.sleep  阻塞式
    /**
     2021-01-20 11:45:21.707640+0800 Gunterapple[7599:484137] begin -- <NSThread: 0x600003aa9cc0>{number = 1, name = main}
     2021-01-20 11:45:21.707818+0800 Gunterapple[7599:484137] end -- <NSThread: 0x600003aa9cc0>{number = 1, name = main}
     2021-01-20 11:45:23.708635+0800 Gunterapple[7599:484259] after -- <NSThread: 0x600003af8a40>{number = 4, name = (null)}
     */
    NSLog(@"begin -- %@",[NSThread currentThread]);
    dispatch_async(queue, ^{
        //最好放在子线程中执行，
        [NSThread sleepForTimeInterval:2.0f];
        NSLog(@"after -- %@",[NSThread currentThread]);
    });
    NSLog(@"end -- %@",[NSThread currentThread]);
    
}
#pragma mark - barrier
- (void)barrierGCD{
    /**
        异步并发队列
     2021-01-19 18:38:00.662951+0800 Gunterapple[5150:277828] 1 -- <NSThread: 0x6000031ef600>{number = 3, name = (null)}
     2021-01-19 18:38:00.662951+0800 Gunterapple[5150:277819] 2 -- <NSThread: 0x6000031eed00>{number = 5, name = (null)}
     2021-01-19 18:38:02.668585+0800 Gunterapple[5150:277819] barrier -- <NSThread: 0x6000031eed00>{number = 5, name = (null)}
     2021-01-19 18:38:04.672326+0800 Gunterapple[5150:277819] 3 -- <NSThread: 0x6000031eed00>{number = 5, name = (null)}
     2021-01-19 18:38:04.672332+0800 Gunterapple[5150:277824] 4 -- <NSThread: 0x60000312c500>{number = 6, name = (null)}
     栅栏之上的异步操作没有执行完，下面的操作是不会执行    异步 但是打印出的结果是同步的
     2021-01-19 18:45:26.318143+0800 Gunterapple[5308:283872] 1 -- <NSThread: 0x6000039d9440>{number = 7, name = (null)}
     2021-01-19 18:45:26.318143+0800 Gunterapple[5308:283875] 2 -- <NSThread: 0x600003909280>{number = 3, name = (null)}
     2021-01-19 18:45:26.318215+0800 Gunterapple[5308:283868] 3 -- <NSThread: 0x600003935400>{number = 6, name = (null)}
     2021-01-19 18:45:26.318223+0800 Gunterapple[5308:283878] 4 -- <NSThread: 0x6000039c0780>{number = 8, name = (null)}
     2021-01-19 18:45:28.318837+0800 Gunterapple[5308:283878] barrier -- <NSThread: 0x6000039c0780>{number = 8, name = (null)}
     2021-01-19 18:45:30.322067+0800 Gunterapple[5308:283878] 5 -- <NSThread: 0x6000039c0780>{number = 8, name = (null)}
     2021-01-19 18:45:30.322072+0800 Gunterapple[5308:283868] 7 -- <NSThread: 0x600003935400>{number = 6, name = (null)}
     2021-01-19 18:45:30.322072+0800 Gunterapple[5308:283875] 6 -- <NSThread: 0x600003909280>{number = 3, name = (null)}
     2021-01-19 18:45:30.322159+0800 Gunterapple[5308:283876] 8 -- <NSThread: 0x600003902440>{number = 5, name = (null)}
     
     全局并发队列  在全局并发队列中是不会执行栅栏方法的 但是异步变同步了
     2021-01-19 18:39:33.969712+0800 Gunterapple[5182:278946] 1 -- <NSThread: 0x600003e7ecc0>{number = 6, name = (null)}
     2021-01-19 18:39:33.969860+0800 Gunterapple[5182:278945] 2 -- <NSThread: 0x600003e65ec0>{number = 2, name = (null)}
     2021-01-19 18:39:33.969900+0800 Gunterapple[5182:278937] 3 -- <NSThread: 0x600003e69cc0>{number = 3, name = (null)}
     2021-01-19 18:39:33.969943+0800 Gunterapple[5182:278956] 4 -- <NSThread: 0x600003ead1c0>{number = 7, name = (null)}
     
     子线程过多有时会失灵
     2021-01-19 18:44:29.805626+0800 Gunterapple[5289:283015] 3 -- <NSThread: 0x600000f76880>{number = 3, name = (null)}
     2021-01-19 18:44:29.805666+0800 Gunterapple[5289:283016] barrier -- <NSThread: 0x600000fb6680>{number = 8, name = (null)}
     2021-01-19 18:44:29.805707+0800 Gunterapple[5289:283043] 7 -- <NSThread: 0x600000f5ac40>{number = 9, name = (null)}
     2021-01-19 18:44:29.805719+0800 Gunterapple[5289:283042] 6 -- <NSThread: 0x600000f5b080>{number = 7, name = (null)}
     2021-01-19 18:44:29.805752+0800 Gunterapple[5289:283011] 1 -- <NSThread: 0x600000f6ff80>{number = 4, name = (null)}
     2021-01-19 18:44:29.805752+0800 Gunterapple[5289:283044] 8 -- <NSThread: 0x600000f5b740>{number = 10, name = (null)}
     2021-01-19 18:44:29.805766+0800 Gunterapple[5289:283008] 2 -- <NSThread: 0x600000f5a640>{number = 6, name = (null)}
     2021-01-19 18:44:29.805835+0800 Gunterapple[5289:283014] 5 -- <NSThread: 0x600000fb65c0>{number = 11, name = (null)}
     2021-01-19 18:44:29.805799+0800 Gunterapple[5289:283012] 4 -- <NSThread: 0x600000f73040>{number = 5, name = (null)}
     */
    
    dispatch_queue_t queue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_CONCURRENT);
    //全局并发队列使用栅栏方法有时会失灵
//    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"1 -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"2 -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"3 -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"4 -- %@",[NSThread currentThread]);
    });
    //添加栅栏方法
    dispatch_barrier_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];
        NSLog(@"barrier -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"5 -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"6 -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"7 -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2.0];  //模拟耗时操作
        NSLog(@"8 -- %@",[NSThread currentThread]);
    });
    
}
#pragma mark - GCD 线程间通信
- (void)portGCD{
    //异步情况下
    //全局并发队列
    /**
     2021-01-19 18:31:38.935154+0800 Gunterapple[5038:274325] currentThread -- <NSThread: 0x600001c98580>{number = 5, name = (null)}
     2021-01-19 18:31:40.936755+0800 Gunterapple[5038:274207] currentThread -- <NSThread: 0x600001cc6e00>{number = 1, name = main}
     2021-01-19 18:31:40.937092+0800 Gunterapple[5038:274207] 刷新UI
     */
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    //获取主队列
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(globalQueue, ^{
        //异步追加耗时操作
        [NSThread sleepForTimeInterval:2.0];
        NSLog(@"currentThread -- %@",[NSThread currentThread]);
        
        //回到主队列 刷新UI
        dispatch_async(mainQueue, ^{
            //模拟一下耗时操作
            [NSThread sleepForTimeInterval:2.0];
            NSLog(@"currentThread -- %@",[NSThread currentThread]);
            NSLog(@"刷新UI");
        });
    });
    
    
}
#pragma mark - GCD组合使用
- (void)creatGCD{
    //创建一个串行队列
//    dispatch_queue_t queue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_SERIAL);
    //创建一个并发队列
//    dispatch_queue_t  concurrentQueue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_CONCURRENT);
    //创建主队列
//    dispatch_queue_t  mainQueue = dispatch_get_main_queue();
    //获取全局并发队列
//    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //创建任务
    //同步
//    dispatch_sync(globalQueue, ^{
//        NSLog(@"HH");
//    });
    //异步
//    dispatch_async(globalQueue, ^{
//        NSLog(@"HH");
//    });
    
    //同步并发
//    dispatch_queue_t queue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_CONCURRENT);
    /**
     串行的在当前线程执行任务，也就是主线程上执行任务
     2021-01-19 18:05:55.019226+0800 Gunterapple[4553:256981] currentThread -- <NSThread: 0x600000a8e180>{number = 1, name = main}
     2021-01-19 18:05:55.019369+0800 Gunterapple[4553:256981] begin
     2021-01-19 18:05:57.020765+0800 Gunterapple[4553:256981] 1 -- <NSThread: 0x600000a8e180>{number = 1, name = main}
     2021-01-19 18:05:59.022372+0800 Gunterapple[4553:256981] 2 -- <NSThread: 0x600000a8e180>{number = 1, name = main}
     2021-01-19 18:06:01.023952+0800 Gunterapple[4553:256981] 3 -- <NSThread: 0x600000a8e180>{number = 1, name = main}
     2021-01-19 18:06:01.024279+0800 Gunterapple[4553:256981] end
     */
//    NSLog(@"currentThread -- %@",[NSThread currentThread]);
//    NSLog(@"begin");
//    dispatch_sync(queue, ^{
//        //模拟耗时操作
//        [NSThread sleepForTimeInterval:2.0];
//        NSLog(@"1 -- %@",[NSThread currentThread]);
//    });
//    dispatch_sync(queue, ^{
//        //模拟耗时操作
//        [NSThread sleepForTimeInterval:2.0];
//        NSLog(@"2 -- %@",[NSThread currentThread]);
//    });
//    dispatch_sync(queue, ^{
//        //模拟耗时操作
//        [NSThread sleepForTimeInterval:2.0];
//        NSLog(@"3 -- %@",[NSThread currentThread]);
//    });
//    NSLog(@"end");
    //异步并发
    /**
     2021-01-19 18:10:44.184109+0800 Gunterapple[4629:259681] currentThread -- <NSThread: 0x600003b65180>{number = 1, name = main}
     2021-01-19 18:10:44.184277+0800 Gunterapple[4629:259681] begin
     2021-01-19 18:10:44.184420+0800 Gunterapple[4629:259681] end
     2021-01-19 18:10:45.184804+0800 Gunterapple[4629:259750] 2 -- <NSThread: 0x600003b3f200>{number = 4, name = (null)}
     2021-01-19 18:10:45.184801+0800 Gunterapple[4629:259746] 1 -- <NSThread: 0x600003b53940>{number = 5, name = (null)}
     2021-01-19 18:10:45.184801+0800 Gunterapple[4629:259755] 3 -- <NSThread: 0x600003b3f680>{number = 3, name = (null)}
     开启新的线程执行任务，没有无序的 可以同时的执行3个任务
     */
//    dispatch_queue_t queue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_CONCURRENT);
//    NSLog(@"currentThread -- %@",[NSThread currentThread]);
//    NSLog(@"begin");
//    //在此处开启新线程 没有延迟的继续执行任务
//    dispatch_async(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"1 -- %@",[NSThread currentThread]);
//    });
//    dispatch_async(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"2 -- %@",[NSThread currentThread]);
//    });
//
//    dispatch_async(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"3 -- %@",[NSThread currentThread]);
//    });
//    NSLog(@"end");
    //同步串行
    /**
     2021-01-19 18:15:41.984123+0800 Gunterapple[4699:262548] currentThread -- <NSThread: 0x600001dafb80>{number = 1, name = main}
     2021-01-19 18:15:41.984279+0800 Gunterapple[4699:262548] begin
     2021-01-19 18:15:42.985221+0800 Gunterapple[4699:262548] 1 -- <NSThread: 0x600001dafb80>{number = 1, name = main}
     2021-01-19 18:15:43.986579+0800 Gunterapple[4699:262548] 2 -- <NSThread: 0x600001dafb80>{number = 1, name = main}
     2021-01-19 18:15:44.988174+0800 Gunterapple[4699:262548] 3 -- <NSThread: 0x600001dafb80>{number = 1, name = main}
     2021-01-19 18:15:44.988468+0800 Gunterapple[4699:262548] end
     */
//    dispatch_queue_t queue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_SERIAL);
//    NSLog(@"currentThread -- %@",[NSThread currentThread]);
//    NSLog(@"begin");
//    dispatch_sync(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"1 -- %@",[NSThread currentThread]);
//    });
//    dispatch_sync(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"2 -- %@",[NSThread currentThread]);
//    });
//    dispatch_sync(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"3 -- %@",[NSThread currentThread]);
//    });
//    NSLog(@"end");
    //异步串行
    /**
     2021-01-20 10:27:22.391414+0800 Gunterapple[6666:437546] currentThread -- <NSThread: 0x60000232d300>{number = 1, name = main}
     2021-01-20 10:27:22.391618+0800 Gunterapple[6666:437546] begin -- <NSThread: 0x60000232d300>{number = 1, name = main}
     2021-01-20 10:27:22.391780+0800 Gunterapple[6666:437546] end -- <NSThread: 0x60000232d300>{number = 1, name = main}
     2021-01-20 10:27:23.397593+0800 Gunterapple[6666:437683] 1 -- <NSThread: 0x60000237da00>{number = 5, name = (null)}
     2021-01-20 10:27:24.401056+0800 Gunterapple[6666:437683] 2 -- <NSThread: 0x60000237da00>{number = 5, name = (null)}
     2021-01-20 10:27:25.404645+0800 Gunterapple[6666:437683] 3 -- <NSThread: 0x60000237da00>{number = 5, name = (null)}
     有开启新的线程 只是一条而已， 异步添加的操作是放在子线程上执行 而且是同步执行的
     */
//    dispatch_queue_t queue = dispatch_queue_create("com.dianYaNetwork.www", DISPATCH_QUEUE_SERIAL);
//    NSLog(@"currentThread -- %@",[NSThread currentThread]);
//    NSLog(@"begin -- %@",[NSThread currentThread]);
//    dispatch_async(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"1 -- %@",[NSThread currentThread]);
//    });
//    dispatch_async(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"2 -- %@",[NSThread currentThread]);
//    });
//    dispatch_async(queue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"3 -- %@",[NSThread currentThread]);
//    });
//    NSLog(@"end -- %@",[NSThread currentThread]);
    //同步主队列
    /**
     Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
     直接奔溃 死锁
     */
//    dispatch_queue_t mainqueue = dispatch_get_main_queue();
//
//    dispatch_sync(mainqueue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"1 -- %@",[NSThread currentThread]);
//    });
//    dispatch_sync(mainqueue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"2 -- %@",[NSThread currentThread]);
//    });
//    dispatch_sync(mainqueue, ^{
//        [NSThread sleepForTimeInterval:1];
//        NSLog(@"3 -- %@",[NSThread currentThread]);
//    });

    
    //异步主队列
    /**
    2021-01-20 10:30:54.498636+0800 Gunterapple[6730:440774] currentThread -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:54.498895+0800 Gunterapple[6730:440774] begin -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:54.499107+0800 Gunterapple[6730:440774] end -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:55.534144+0800 Gunterapple[6730:440774] 1 -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:56.534514+0800 Gunterapple[6730:440774] 2 -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:57.535844+0800 Gunterapple[6730:440774] 3 -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:58.537286+0800 Gunterapple[6730:440774] 4 -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:30:59.538933+0800 Gunterapple[6730:440774] 5 -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     2021-01-20 10:31:00.540280+0800 Gunterapple[6730:440774] 6 -- <NSThread: 0x6000036ade80>{number = 1, name = main}
     有开启新的线程，也只是一条   同上，异步串行和异步主队列是一个性质，可知主队列也是一个串行队列   （异步变同步）
     
     虽然是异步但是没有开启新的线程执行新加的任务，所有的任务都在主队列中执行
     */
    dispatch_queue_t mainqueue = dispatch_get_main_queue();
    NSLog(@"currentThread -- %@",[NSThread currentThread]);
    NSLog(@"begin -- %@",[NSThread currentThread]);
    dispatch_async(mainqueue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"1 -- %@",[NSThread currentThread]);
    });
    dispatch_async(mainqueue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"2 -- %@",[NSThread currentThread]);
    });
    dispatch_async(mainqueue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"3 -- %@",[NSThread currentThread]);
    });
    dispatch_async(mainqueue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"4 -- %@",[NSThread currentThread]);
    });
    dispatch_async(mainqueue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"5 -- %@",[NSThread currentThread]);
    });
    dispatch_async(mainqueue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"6 -- %@",[NSThread currentThread]);
    });
    NSLog(@"end -- %@",[NSThread currentThread]);
    
}
#pragma mark - thread 线程间通信
- (void)threadPort{
    [NSThread detachNewThreadWithBlock:^{
        NSLog(@"currentThread -- %@",[NSThread currentThread]);
        //模拟耗时操作
        for (int i = 0; i < 3; i ++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"currentThread 耗时操作 -- %@",[NSThread currentThread]);
        }
        NSLog(@"网络请求成功 准备回到主线程刷新 UI  %@",[NSThread currentThread]);
        //回主线程刷新UI
        [self performSelectorOnMainThread:@selector(setUpUI) withObject:nil waitUntilDone:YES];
    }];
}
#pragma mark - thread
- (void)thread{
    //实例方法创建子线程的三种方法
    //1.sel
    /**
     注意需要设置线程的名称和优先级，并start
     */
    NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(click) object:nil];
    thread1.name = @"thread1";
    //设置线程优先级 调度优先级的取值范围是0.0 ~ 1.0，默认0.5，值越大，优先级越高。
    thread1.threadPriority = 0.5;
    //启动线程
    [thread1 start];
    
    //
//    [NSThread exit];
    
    //2.alloc init
//    NSThread *thread2 =  [[NSThread alloc]init];

    //3.block
    NSThread *thread3 = [[NSThread alloc]initWithBlock:^{
        NSLog(@"currentThread3 -- %@",[NSThread currentThread]);
    }];
    thread3.threadPriority = 0.6;
    [thread3 start];
    
    //线程是否正在执行
    /**
     (lldb) po [thread1 isExecuting]
     NO

     (lldb) po [thread1 isFinished]
     <nil>

     (lldb) po [thread1 isCancelled]
     <nil>
     */
   if([thread1 isExecuting]){
       NSLog(@"thread1 is executing!");
   }
    //线程是否执行完毕
//    if([thread1 isFinished]){
//        NSLog(@"thread1 is Finished");
//    }
    //取消线程
//    [thread1 cancel];
    
    
     //线程是否撤销
//    if([thread1 isCancelled]){
//        NSLog(@"thread1 is Cancelled");
//    }
    
//     创建线程后自动启动线程
    //1.block
//    [NSThread detachNewThreadWithBlock:^{
//        NSLog(@"类方法1 block 创建 thread : %s : %@", __func__, [NSThread currentThread]);
//    }];
    //设置优先级
//    [NSThread setThreadPriority:0.3];
    
    // 线程沉睡时间间隔 常用在设置启动页间隔 可以将两条线程隔开
//    [NSThread sleepForTimeInterval:1.0];
    //2.SEL
    [NSThread detachNewThreadSelector:@selector(threadClick2) toTarget:self withObject:nil];
    [NSThread setThreadPriority:0.5];
    //会把主线程杀掉， 不要使用 小心使用
//    [NSThread exit];
    
}
- (void)setUpUI{
    
    NSLog(@"回到了主线程并且刷新 UI  %s : %@", __func__, [NSThread currentThread]);
    
}
- (void)click{
    
    NSLog(@"currentThread1 -- %@",[NSThread currentThread]);
    [NSThread exit];
    NSLog(@"currentThread1 -- %@",[NSThread currentThread]);
    
}

- (void)threadClick2{
    NSInteger stackSize = [[NSThread currentThread] stackSize];
    NSLog(@" 创建线程后自动启动线程 thread : %s : %@", __func__, [NSThread currentThread]);
    /**
     stackSize -- 524288
     子线程的栈大小就是512KB
     */
    NSLog(@"stackSize -- %ld",stackSize);
}
- (void)dealloc{
    [self.timer invalidate];
    self.timer = nil;
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
